package proto

import (
	"bytes"
	_ "bytes"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

// 16进制数组转16进制字符串
func HexToHexStr(buf []byte) string {
	len := len(buf)
	if buf == nil || len <= 0 {
		return ""
	}
	str := fmt.Sprintf("%02X", buf[0])
	for i := 1; i < len; i++ {
		str += fmt.Sprintf(" %02X", buf[i])
	}
	return str
}

func BytesToHexStr(buf []byte) string {
	len := len(buf)
	if buf == nil || len <= 0 {
		return ""
	}
	str := ""
	for i := 0; i < len; i++ {
		str += fmt.Sprintf("%02X", buf[i])
	}
	return str
}

// 解析16进制字符串为字节切片
func HexStrToBytes(hexStr string) ([]byte, error) {
	bytes, err := hex.DecodeString(hexStr)
	if err != nil {
		return nil, err
	}
	return bytes, nil
}

// 解析16进制字符串为字节切片
func OneByteHexStrToByte(hexStr string) byte {
	bytes, err := hex.DecodeString(hexStr)
	if err != nil {
		return 0
	}
	return bytes[0]
}

// 解析16进制字符串为Int 如 31 32 33 返回 "123"
func HexBytesToInt(hexStr []byte) int64 {
	val, _ := strconv.ParseInt(string(hexStr), 10, 64)
	return val
}

// 解析16进制字符串为文本字符串 如 31 32 33 返回 "123"
func HexDataStrToStr(hexStr string) string {
	bytes, err := hex.DecodeString(hexStr)
	if err != nil {
		return ""
	}
	return string(bytes)
}

// 文本字符 转 16进制字符串为 如 "123" 输出 31 32 33
func StrToHexDataStr(str string) string {
	return strings.ToUpper(hex.EncodeToString([]byte(str)))
}

// 解析16进制字符串为10进制的字符串 如 31 32 33 返回 123
func HexDataStrToInt64(hexStr string) int64 {
	valStr := HexDataStrToStr(hexStr)
	val, _ := strconv.ParseInt(valStr, 10, 64)
	return val
}

// 解析16进制字符串为Int型 如 10 01 返回 16
func ParaIntDataByHexStr(hexStr string) int64 {
	if len(hexStr)%2 != 0 {
		return 0
	}
	byte, _ := HexStrToBytes(hexStr)
	return ParaIntData(byte)
}

//16进制字符串 毫秒 转 时间
func ParaHexStrToTimeMs(hexStr string) time.Time {
	millis := ParaIntDataByHexStr(hexStr)
	return time.Unix(millis/1000, (millis%1000)*1000000)
}

//16进制字符串 秒 转 时间
func ParaHexStrToTimeS(hexStr string) time.Time {
	second := ParaIntDataByHexStr(hexStr)
	return time.Unix(second, 0)
}

// 反转字符串
func reverseData(data []byte) []byte {
	dataLen := len(data)
	var res []byte
	for i := dataLen; i > 0; i-- {
		res = append(res, data[i-1])
	}
	return res
}

//解析参数
func ParaIntData(data []byte) int64 {
	dataLen := len(data)
	var res int64
	res = 0
	for i := 0; i < dataLen; i++ {
		switch i {
		case 0:
			res += int64(data[i])
			break
		case 1:
			res += 128 * int64(data[i]-1)
			break
		case 2:
			res += 128 * 128 * int64(data[i]-1)
			break
		case 3:
			res += 128 * 128 * 128 * int64(data[i]-1)
			break
		case 4:
			res += 128 * 128 * 128 * 128 * int64(data[i]-1)
			break
		case 5:
			res += 128 * 128 * 128 * 128 * 128 * int64(data[i]-1)
			break
		default:
			break

		}
	}
	return res
}

func IntDataToHexStr(value int64) string {
	return BytesToHexStr(IntDataToBytes(value))
}

func IntDataToBytes(value int64) []byte {
	var bytes []byte
	var HexData [6]byte
	HexData[0] = byte(value % 128)
	value -= value % 128
	if value >= 128 {
		HexData[0] += 128
		value -= 128
	}
	//log.Infof("HexData[0] = 0x%02x %d", HexData[0], value)

	HexData[1] = byte((value%(128*128))/128) + 1
	value -= value % (128 * 128)
	if value > 128*128 {
		HexData[1] += 128
		value -= 128 * 128
	}
	//log.Infof("HexData[1] = 0x%02x %d", HexData[1], value)

	HexData[2] = byte((value%(128*128*128))/(128*128)) + 1
	value -= value % (128 * 128 * 128)
	if value > 128*128*128 {
		HexData[2] += 128
		value -= 128 * 128 * 128
	}
	//log.Infof("HexData[2] = 0x%02x %d", HexData[2], value)

	HexData[3] = byte((value%(128*128*128*128))/(128*128*128)) + 1
	value -= value % (128 * 128 * 128 * 128)
	if value > 128*128*128*128 {
		HexData[3] += 128
		value -= 128 * 128 * 128 * 128
	}
	//log.Infof("HexData[3] = 0x%02x %d", HexData[3], value)

	HexData[4] = byte((value%(128*128*128*128*128))/(128*128*128*128)) + 1
	value -= value % (128 * 128 * 128 * 128 * 128)
	if value > 128*128*128*128*128 {
		HexData[4] += 128
		value -= 128 * 128 * 128 * 128 * 128
	}
	//log.Infof("HexData[4] = 0x%02x %d", HexData[4], value)

	HexData[5] = byte((value%(128*128*128*128*128*128))/(128*128*128*128*128)) + 1
	value -= value % (128 * 128 * 128 * 128 * 128 * 128)
	if value > 128*128*128*128*128*128 {
		HexData[5] += 128
		value -= 128 * 128 * 128 * 128 * 128 * 128
	}
	//log.Infof("HexData[5] = 0x%02x %d", HexData[5], value)
	bytes = append(bytes, HexData[0])
	for i := 1; i < 6; i++ {
		if HexData[i] <= 1 {
			break
		}
		bytes = append(bytes, HexData[i])
	}
	return bytes
}

// 解析消息数据
func DecodeMsgData(hexData []byte) (*MsgData, error) {
	msgData := &MsgData{
		Data:    nil,
		HexData: nil,
		JsData:  nil,
	}
	if len(hexData) < 18 {
		return nil, fmt.Errorf("data len too short")
	}
	// 解析头部信息
	err := binary.Read(bytes.NewReader(hexData[:2]), binary.BigEndian, &(msgData.Head))
	if err != nil {
		return nil, err
	}

	// 解析数据总长度
	err = binary.Read(bytes.NewReader(hexData[2:6]), binary.BigEndian, &(msgData.TotalLen))
	if err != nil {
		return nil, err
	}

	// 解析控制命令
	err = binary.Read(bytes.NewReader(hexData[6:10]), binary.BigEndian, &(msgData.Cmd))
	if err != nil {
		return nil, err
	}

	// 解析玩家ID
	err = binary.Read(bytes.NewReader(hexData[10:18]), binary.BigEndian, &(msgData.PlayerID))
	if err != nil {
		return nil, err
	}
	hexData = hexData[18:]

	tmpData := hexData
	msgData.HexData = tmpData
	// 循环解析参数
	for len(hexData) > 0 {
		paramCode := hexData[0]
		paramLen := int(hexData[1])
		if len(hexData) < paramLen+2 {
			break
		}
		paramValue := hexData[2 : paramLen+2]
		// 将参数添加到JsData切片中
		msgData.JsData = append(msgData.JsData, JsData{
			Code:    paramCode,
			Data:    string(paramValue),
			HexData: paramValue,
		})
		if len(hexData) < (paramLen+2)+2 {
			break
		}
		hexData = hexData[paramLen+2:]
	}
	return msgData, nil
}

//打印剩余时间
func PrintRemainTime(leftTime time.Duration) string {
	if leftTime < 0 {
		return ""
	}
	hours := int(leftTime.Hours())
	minutes := int(leftTime.Minutes()) % 60
	seconds := int(leftTime.Seconds()) % 60
	return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
}

/*
71-AB : c.NetSocket.HEADER 头部信息，固定为 29099
00-00-00-30 : 数据总长度 48
00-00-4E-21 : cmd  控制命令 S_PLAYER_LOGIN  = 20001
00-00-02-D4-07-01-81-E2 : 玩家ID 3109673861602
*/
func EncodeMsgData(msgData *MsgData) []byte {
	var buf bytes.Buffer
	msgData.Head = ProtoHead

	// 写入头部信息
	err := binary.Write(&buf, binary.BigEndian, msgData.Head)
	if err != nil {
		return nil
	}

	// 写入数据总长度
	err = binary.Write(&buf, binary.BigEndian, msgData.TotalLen)
	if err != nil {
		return nil
	}

	// 写入控制命令
	err = binary.Write(&buf, binary.BigEndian, msgData.Cmd)
	if err != nil {
		return nil
	}

	// 写入玩家ID
	err = binary.Write(&buf, binary.BigEndian, msgData.PlayerID)
	if err != nil {
		return nil
	}

	//格式化输入参数为byte数组
	EncodeCmdData(msgData)

	if msgData.JsData != nil {
		// 写入JsData数组
		for _, jsData := range msgData.JsData {
			// 写入参数名
			err = buf.WriteByte(jsData.Code)
			if err != nil {
				return nil
			}
			// 写入参数值长度
			err = buf.WriteByte(byte(len(jsData.Data)))
			if err != nil {
				return nil
			}
			// 写入参数值
			_, err = buf.WriteString(string(jsData.HexData))
			if err != nil {
				return nil
			}
		}
	} else if msgData.HexData != nil {
		_, err = buf.WriteString(string(msgData.HexData))
		if err != nil {
			return nil
		}
	}
	// 计算总长度（包括头部、控制命令、玩家ID和JsData）
	msgData.TotalLen = int32(buf.Len())
	// 将TotalLen的四个字节分别写入到buf的相应位置
	buf.Bytes()[2] = byte(msgData.TotalLen >> 24)
	buf.Bytes()[3] = byte(msgData.TotalLen >> 16)
	buf.Bytes()[4] = byte(msgData.TotalLen >> 8)
	buf.Bytes()[5] = byte(msgData.TotalLen)
	return buf.Bytes()
}

//将输入参数转为16进制数据
func EncodeCmdData(msgData *MsgData) {
	var buf bytes.Buffer

	switch msgData.Data.(type) {
	case S_PLAYER_LOGIN_data:
		/*协议解析
		0A : 对应参数名 token
		15 : 对应参数长度为15个字节
		75-4F-30-5F-4F-4F-43-4A-62-78-6C-55-46-41-44-32-61-75-6B-31-52 : 参数token的值uO0_OOCJbxlUFAD2auk1R
		12 : 对应参数名 language
		05 : 对应参数长度为5个字节
		7A-68-5F-63-6E : 参数language的值zh_cn
		*/
		data := msgData.Data.(S_PLAYER_LOGIN_data)
		if buf.WriteByte(0x0A) != nil {
			return
		}
		if buf.WriteByte(byte(len(data.Token))) != nil {
			return
		}
		_, err := buf.WriteString(data.Token)
		if err != nil {
			return
		}
		if buf.WriteByte(0x12) != nil {
			return
		}
		if buf.WriteByte(byte(len(data.Language))) != nil {
			return
		}
		_, err = buf.WriteString(data.Language)
		if err != nil {
			return
		}
		if buf.WriteByte(0x18) != nil {
			return
		}
		if buf.WriteByte(0x02) != nil {
			return
		}
		msgData.HexData = buf.Bytes()
		//log.Debug("S_PLAYER_LOGIN_data:", HexToHexStr(msgData.HexData))
		return

	default:
		return
	}
}

// getRandomNum generates a random string of specified length using characters 0-9, a-z, A-Z.
func GetRandomNum(count int) string {
	const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	rand.Seed(time.Now().UnixNano())
	var result strings.Builder

	for i := 0; i < count; i++ {
		index := rand.Intn(len(chars))
		result.WriteByte(chars[index])
	}

	return result.String()
}
